-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix OIDC introspection authentication #31632
Conversation
The introspect endpoint was using the OIDC token itself for authentication. This fixes it to use basic authentication with the client ID and secret instead: * Applications with a valid client ID and secret should be able to successfully introspect an invalid token, receiving a 200 response with JSON data that indicates the token is invalid * Requests with an invalid client ID and secret should not be able to introspect, even if the token itself is valid
Co-authored-by: Lauris BH <[email protected]>
@techknowlogick re. your question on #31632 about integration testing, I think the automated integration test added here is a pretty good description of the flow: first you issue a token from I did a successful end-to-end test of an IRCv3 integration (it needed one additional patch, to add the |
Why is this PR breaking? |
I updated the description. tl;dr after this change, clients using the introspection endpoint will need to start sending a valid basic auth header. I could also remove the basic auth check. Okta's rationale for it doesn't make sense to me:
The tokens here are JWTs so they can't be brute-forced, and I don't think DoS is a real concern either. But I would like someone with more OIDC expertise to weigh in on this :-) |
While rate-limiting is definitely a concern, it can be considered as out-of-scope for this PR. I also am not sure we need to be concerned with this opening up a venue for malicious users to see if a token is valid or not, as that can essentially be done with any endpoint. |
Usually introspection tokens are not jwt tokens so they cannot be validated and introspection endpoint is used to do that and that's why it requires separate auth so that only valid clients can do that. On the other hand even if jwt token is used introspection endpoint can be used to check if session is still valid even if jwt token is not expired itself |
Just checking if there are still any open issues blocking a merge? |
* origin/main: (59 commits) fix OIDC introspection authentication (go-gitea#31632) Enable direnv (go-gitea#31672) [skip ci] Updated translations via Crowdin [skip ci] Updated translations via Crowdin fix redis dep (go-gitea#31662) add skip secondary authorization option for public oauth2 clients (go-gitea#31454) Fix a branch divergence cache bug (go-gitea#31659) [skip ci] Updated translations via Crowdin Remove unneccessary uses of `word-break: break-all` (go-gitea#31637) [skip ci] Updated translations via Crowdin Allow searching issues by ID (go-gitea#31479) allow synchronizing user status from OAuth2 login providers (go-gitea#31572) Enable `no-jquery/no-class-state` (go-gitea#31639) Added default sorting milestones by name (go-gitea#27084) Code editor theme enhancements (go-gitea#31629) Add option to change mail from user display name (go-gitea#31528) Upgrade xorm to v1.3.9 and improve some migrations Sync (go-gitea#29899) Issue Templates: add option to have dropdown printed list (go-gitea#31577) Fix update flake (go-gitea#31626) [skip ci] Updated translations via Crowdin ...
* giteaofficial/main: use nolyfill to remove some polyfills (go-gitea#31468) Properly filter issue list given no assignees filter (go-gitea#31522) Run `detectWebAuthnSupport` only on sign-in page (go-gitea#31676) fix OIDC introspection authentication (go-gitea#31632) Enable direnv (go-gitea#31672) [skip ci] Updated translations via Crowdin [skip ci] Updated translations via Crowdin
@@ -326,10 +325,29 @@ func getOAuthGroupsForUser(ctx go_context.Context, user *user_model.User) ([]str | |||
return groups, nil | |||
} | |||
|
|||
func parseBasicAuth(ctx *context.Context) (username, password string, err error) { | |||
authHeader := ctx.Req.Header.Get("Authorization") | |||
if authType, authData, ok := strings.Cut(authHeader, " "); ok && authType == "Basic" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe auth scheme "Basic" should be compare case insensitively
"Note that both scheme and parameter names are matched case-insensitively."
https://www.rfc-editor.org/rfc/rfc7617.html#section-2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. @slingamn was that a deliberate change or we just missed it in reviewing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't intentional :-) I just refactored the original implementation (#6293) which was case-sensitive. So there's no behavior change, but I agree that a case-insensitive comparison would be more correct.
@kylef pointed out on #31632 that [RFC7617](https://www.rfc-editor.org/rfc/rfc7617.html#section-2) mandates case-insensitive comparison of the scheme field `Basic`. #31632 copied a case-sensitive comparison from #6293. This PR fixes both comparisons. The issue only affects OIDC, since the implementation for normal Gitea endpoints is already correct: https://github.com/go-gitea/gitea/blob/930ca92d7ce80e8b0bdaf92e495026baf2a1d419/services/auth/basic.go#L55-L58
These are the three conflicted changes from #4716: * go-gitea/gitea#31632 * go-gitea/gitea#31688 * go-gitea/gitea#31706 cc @earl-warren; as per discussion on go-gitea/gitea#31632 this involves a small compatibility break (OIDC introspection requests now require a valid client ID and secret, instead of a valid OIDC token) ## Checklist The [developer guide](https://forgejo.org/docs/next/developer/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org). ### Tests - I added test coverage for Go changes... - [ ] in their respective `*_test.go` for unit tests. - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server. ### Documentation - [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. - [ ] I did not document these changes and I do not expect someone else to do it. ### Release notes - [ ] I do not want this change to show in the release notes. - [ ] I want the title to show in the release notes with a link to this pull request. - [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title. <!--start release-notes-assistant--> ## Draft release notes <!--URL:https://codeberg.org/forgejo/forgejo--> - Breaking features - [PR](https://codeberg.org/forgejo/forgejo/pulls/4724): <!--number 4724 --><!--line 0 --><!--description T0lEQyBpbnRlZ3JhdGlvbnMgdGhhdCBQT1NUIHRvIGAvbG9naW4vb2F1dGgvaW50cm9zcGVjdGAgd2l0aG91dCBzZW5kaW5nIEhUVFAgYmFzaWMgYXV0aGVudGljYXRpb24gd2lsbCBub3cgZmFpbCB3aXRoIGEgNDAxIEhUVFAgVW5hdXRob3JpemVkIGVycm9yLiBUbyBmaXggdGhlIGVycm9yLCB0aGUgY2xpZW50IG11c3QgYmVnaW4gc2VuZGluZyBIVFRQIGJhc2ljIGF1dGhlbnRpY2F0aW9uIHdpdGggYSB2YWxpZCBjbGllbnQgSUQgYW5kIHNlY3JldC4gVGhpcyBlbmRwb2ludCB3YXMgcHJldmlvdXNseSBhdXRoZW50aWNhdGVkIHZpYSB0aGUgaW50cm9zcGVjdGlvbiB0b2tlbiBpdHNlbGYsIHdoaWNoIGlzIGxlc3Mgc2VjdXJlLg==-->OIDC integrations that POST to `/login/oauth/introspect` without sending HTTP basic authentication will now fail with a 401 HTTP Unauthorized error. To fix the error, the client must begin sending HTTP basic authentication with a valid client ID and secret. This endpoint was previously authenticated via the introspection token itself, which is less secure.<!--description--> <!--end release-notes-assistant--> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/4724 Reviewed-by: Earl Warren <[email protected]> Co-authored-by: Shivaram Lingamneni <[email protected]> Co-committed-by: Shivaram Lingamneni <[email protected]>
See discussion on #31561 for some background.
The introspect endpoint was using the OIDC token itself for
authentication. This fixes it to use basic authentication with the
client ID and secret instead:
successfully introspect an invalid token, receiving a 200 response
with JSON data that indicates the token is invalid
to introspect, even if the token itself is valid
Unlike #31561 (which just future-proofed the current behavior against future changes to
DISABLE_QUERY_AUTH_TOKEN
), this is a potential compatibility break (some introspection requests without valid client IDs that would previously succeed will now fail). Affected deployments must begin sending a valid HTTP basic authentication header with their introspection requests, with the username set to a valid client ID and the password set to the corresponding client secret.